
/*
 * Copyright 2008 Friendster Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
 
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and limitations under the License.
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Friendster.Service.Core;
using System.IO;

namespace Friendster.Service
{
    /// <summary>
    /// Provide methods for accessing Friendster user photos
    /// </summary>
    public sealed class PhotosService
    {
        // Fields
        private string _session;

        // Methods
        /// <summary>
        /// Initilizes the session for using the service.
        /// </summary>
        /// <param name="session"></param>
        internal PhotosService(string session)
        {
            this._session = session;
        }
        /// <summary>
        /// Returns the collection of all the photos for given user.
        /// </summary>
        /// <param name="userID"></param>
        /// <returns>Collection of Photo object</returns>
        public ICollection<Photo> GetPhotosOfUser(string userID)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);
            if (string.IsNullOrEmpty(userID))
            {
                userID = request.UserID;
            }

            FriendsterResponse response = request.InvokeMethod("GET", "photos/" + userID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                for (int i = 0; i < result.Count; i++)
                {
                    result[i] = new Photo((Hashtable)result[i]);
                }
                return (Photo[])result.ToArray(typeof(Photo));
            }
            return null;
        }
        /// <summary>
        /// Returns the collection of photos for current logged in user.
        /// </summary>
        /// <returns>Collection of Photo object</returns>
        public ICollection<Photo> GetPhotosOfUser()
        {
            return this.GetPhotosOfUser(null);
        }
        /// <summary>
        /// Uploads the given photo for the specified user.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="filename"></param>
        /// <param name="photoStream"></param>
        /// <param name="contentType"></param>
        /// <param name="caption"></param>
        /// <param name="albumID"></param>
        /// <returns>Uploaded Photo object</returns>
        public Photo UploadPhoto(string userID, string filename, Stream photoStream, string contentType, string caption, string albumID)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);

            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }
            if (photoStream == null)
            {
                throw new ArgumentNullException("photoStream");
            }

            FriendsterResponse response = request.UploadFile(userID, filename, photoStream, contentType, caption, albumID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                return new Photo((Hashtable)result[0]);
            }
            return null;
        }
        /// <summary>
        /// Uploads the given photo for current logged in user.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="photoStream"></param>
        /// <param name="contentType"></param>
        /// <param name="caption"></param>
        /// <param name="albumID"></param>
        /// <returns>Uploaded Photo object</returns>
        public Photo UploadPhoto(string filename, Stream photoStream, string contentType, string caption, string albumID)
        {
            return UploadPhoto(null, filename, photoStream, contentType, caption, albumID);
        }
        /// <summary>
        /// Uploads the given photo for the specified user.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="filename"></param>
        /// <param name="photoStream"></param>
        /// <param name="contentType"></param>
        /// <param name="caption"></param>
        /// <returns>Uploaded Photo object</returns>
        public Photo UploadPhoto(string userID, string filename, Stream photoStream, string contentType, string caption)
        {
            return UploadPhoto(userID, filename, photoStream, contentType, "0");
        }
        /// <summary>
        /// Uploads the given photo for current logged in user.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="photoStream"></param>
        /// <param name="contentType"></param>
        /// <param name="caption"></param>
        /// <returns>Uploaded Photo object</returns>
        public Photo UploadPhoto(string filename, Stream photoStream, string contentType, string caption)
        {
            return UploadPhoto(null, filename, photoStream, contentType, caption, "0");
        }
        /// <summary>
        /// Get the photo specified userID (owner) and photoID.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="photoID"></param>
        /// <returns>Photo object</returns>
        public Photo GetPhoto(string userID, string photoID)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);
            if (string.IsNullOrEmpty(userID))
                {
                userID = request.UserID;
            }

            FriendsterResponse response = request.InvokeMethod("GET", "photo/" + userID + "/"+ photoID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                return new Photo((Hashtable)result[0]);
            }
            return null;
        }
        /// <summary>
        /// Gets the photo (specified by photoID) of current logged in user.
        /// </summary>
        /// <param name="photoID"></param>
        /// <returns></returns>
        public Photo GetPhoto(string photoID)
        {
            return GetPhoto(null, photoID);
        }
        /// <summary>
        /// Updates the caption and isPrimary flag of a photo (given by photoID) for a specified user.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="photoID"></param>
        /// <param name="caption"></param>
        /// <param name="isPrimary"></param>
        /// <returns>Updated Photo object</returns>
        public Photo UpdatePhoto(string userID, string photoID, string caption, bool isPrimary)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);
            if (string.IsNullOrEmpty(userID))
            {
                userID = request.UserID;
            }

            request.Parameters.Add("uid", userID);
            request.Parameters.Add("pid", photoID);
            if(isPrimary)
                request.Parameters.Add("isprimary", "1");
            if(!string.IsNullOrEmpty(caption))
                request.Parameters.Add("caption", caption);
            
            FriendsterResponse response = request.InvokeMethod("PUT", "photo/" + userID + "/" + photoID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                return new Photo((Hashtable)result[0]);
            }
            return null;
         }
        /// <summary>
        /// Updates the caption and isPrimary flag of given photo.
        /// </summary>
        /// <param name="photoID"></param>
        /// <param name="caption"></param>
        /// <param name="isPrimary"></param>
        /// <returns>Photo object</returns>
        public Photo UpdatePhoto(string photoID, string caption, bool isPrimary)
        {
            return UpdatePhoto(null, photoID, caption, isPrimary);
        }
        /// <summary>
        /// Gets the primary photo of specified user.
        /// </summary>
        /// <param name="userID"></param>
        /// <returns>Photo object</returns>
        public Photo GetPrimaryPhoto(string userID)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);
            if (string.IsNullOrEmpty(userID))
            {
                userID = request.UserID;
            }

            request.Parameters.Add("uid", userID);
            FriendsterResponse response = request.InvokeMethod("GET", "primaryphoto/" + userID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                return new Photo((Hashtable)result[0]);
            }
            return null;
        }
        /// <summary>
        /// Gets the primary photo of current logged in user.
        /// </summary>
        /// <returns>Photo object</returns>
        public Photo GetPrimaryPhoto()
        {
            return GetPrimaryPhoto(null);
        }
        /// <summary>
        /// Deletes the photo of user specified by photoId and userId.
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="photoID"></param>
        /// <returns>Boolean value of success or failure</returns>
        public bool DeletePhoto(string userID, string photoID)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);
            if (string.IsNullOrEmpty(userID))
            {
                userID = request.UserID;
            }

            request.Parameters.Add("uid",userID);
            request.Parameters.Add("pid",photoID);
            FriendsterResponse response = request.InvokeMethod("DELETE", "photo/" + userID + "/" + photoID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                return true;
            }
            return false;

        }
        /// <summary>
        /// Deletes the specified photo for current logged in user.
        /// </summary>
        /// <param name="photoID"></param>
        /// <returns></returns>
        public bool DeletePhoto(string photoID)
        {
            return DeletePhoto(null,photoID);
        }

        public ICollection<Album> GetAlbums(string userID, ICollection<string> albumIDs)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);
            if (string.IsNullOrEmpty(userID))
            {
                userID = request.UserID;
            }
            if ((albumIDs != null) && (albumIDs.Count != 0))
            {
                StringBuilder builder = new StringBuilder();
                foreach (string str in albumIDs)
                {
                    if (builder.Length != 0)
                    {
                        builder.Append(",");
                    }
                    builder.Append(str);
                }
                request.Parameters["aids"] = builder.ToString();
            }
            FriendsterResponse response = request.InvokeMethod("GET", "albums/" + userID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                for (int i = 0; i < result.Count; i++)
                {
                    result[i] = new Album((Hashtable)result[i]);
                }
                return (Album[])result.ToArray(typeof(Album));
            }
            return null;
        }
        /// <summary>
        /// Returns the album of current user specified by albumID
        /// </summary>
        /// <param name="albumID"></param>
        /// <returns></returns>
        public Album GetAlbum(string albumID)
        {
            if (string.IsNullOrEmpty("albumID"))
            {
                throw new ArgumentNullException("albumID");
            }
            ICollection<Album> albums = this.GetAlbums(null, new string[] { albumID });
            if ((albums != null) && (albums.Count != 0))
            {
                foreach (Album album in albums)
                {
                    return album;
                }
            }
            return null;
        }
        /// <summary>
        /// Returns album (specified ID) of user (specified ID)
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="albumID"></param>
        /// <returns></returns>
        public Album GetAlbum(string userID, string albumID)
        {
            if (string.IsNullOrEmpty("albumID"))
            {
                throw new ArgumentNullException("albumID");
            }

            ICollection<Album> albums = this.GetAlbums(userID, new string[] { albumID });
            if ((albums != null) && (albums.Count != 0))
            {
                foreach (Album album in albums)
                {
                    return album;
                }
            }
            return null;
        }
        /// <summary>
        /// Returns albums information (specified by albumIds) of current user
        /// </summary>
        /// <param name="albumIDs"></param>
        /// <returns></returns>
        public ICollection<Album> GetAlbums(ICollection<string> albumIDs)
        {
            if ((albumIDs == null) || (albumIDs.Count == 0))
            {
                throw new ArgumentNullException("albumIDs");
            }
            return this.GetAlbums(null, albumIDs);
        }
        /// <summary>
        /// Returns all album of specified user
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public ICollection<Album> GetAlbumsOfUser(string userID)
        {
            return this.GetAlbums(userID, null);
        }
        /// <summary>
        /// Returns all albums of current user
        /// </summary>
        /// <returns></returns>
        public ICollection<Album> GetAlbumsOfUser()
        {
            return this.GetAlbums(null, null);
        }
        /// <summary>
        /// Creates a new album and returns created album information
        /// </summary>
        /// <param name="albumName"></param>
        /// <param name="isPrivate"></param>
        /// <returns></returns>
        public Album CreateAlbum(string albumName, bool isPrivate)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);

            if (string.IsNullOrEmpty(albumName))
            {
                throw new ArgumentNullException("albumName");
            }

            request.Parameters.Add("name",albumName);
            if(isPrivate)
                request.Parameters.Add("isprivate","1");
            else
                request.Parameters.Add("isprivate", "0");

            FriendsterResponse response = request.InvokeMethod("POST", "album/");
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                return new Album((Hashtable)result[0]);
            }
            return null;
        }
        /// <summary>
        /// Deletes the specified album
        /// </summary>
        /// <param name="albumID"></param>
        /// <param name="preservePhotos"></param>
        /// <returns></returns>
        public bool DeleteAlbum(string albumID, bool preservePhotos)
        {
            FriendsterRequest request = new FriendsterRequest(this._session);

            if (string.IsNullOrEmpty(albumID))
            {
                throw new ArgumentNullException("albumID");
            }

            request.Parameters.Add("aid", albumID);
            if (preservePhotos)
                request.Parameters.Add("preserve_photos", "1");
            else
                request.Parameters.Add("preserve_photos", "0");

            FriendsterResponse response = request.InvokeMethod("DELETE", "album/" + albumID);
            if (!response.IsError)
            {
                ArrayList result = (ArrayList)response.Result;
                Hashtable res = (Hashtable)result[0];
                if (res["status"].ToString() == (string)"SUCCESS")
                    return true;
            }
            return false;
        }
    }
}
